var GameEntity = require('js/gameEntity').GameEntity;
var gamejs = require('gamejs');

/**
 * RADAR: an object representing a radar. The detection area is a circular
 * sector.
 */

 /**
 * Create a Radar object.
 *
 * @param {Match} match The match where this object will work.
 * @param {[number, number]} coords The radar's position, in format [x, y].
 * @param {number} startAngle angle where the detection starts [default 0]
 * @param {number} centralAngle angle covered by the radar [default 2*Math.PI]
 */
var Radar = exports.Radar = function(match, coords, startAngle, centralAngle) {
	// Execute GameEntity constructor
	Radar.superConstructor.call(this, match, coords, Radar.UPGRADE_LIST, true);

	// Attributes with angle things
	this.startAngle = startAngle || 0;
	this.centralAngle = centralAngle || Math.PI*2;
	this.currentAngle = 0;

	// Private attributes holding information on ray lenght
	var dims = this.image.getSize();
	this._minRayLength = 1 + Math.ceil(Math.sqrt(
		Math.pow((dims[0]/2),2) + Math.pow((dims[1]/2), 2))
	);

	// Private attribute holding information on ray "ending point"
	var totalAngle = this.currentAngle + this.startAngle;
	var RayEndX = Math.ceil(
		this.getCenter()[0] + Math.cos(totalAngle) * this.getRadius()
		);
	var RayEndY = Math.ceil(
		this.getCenter()[1] + Math.sin(totalAngle) * this.getRadius()
		);
	this._currentRayEnd = [RayEndX, RayEndY];
};

/**
 * Radar extend GameEntity.
 */
gamejs.utils.objects.extend(Radar, GameEntity);

/**
 * The list of available upgrades
 */
Radar.UPGRADE_LIST = [
	// Level 0
	{ price: 100, resaleValue: 70, radius: 100, angularVelocity: Math.PI / 4,
		image: IMAGE_ROOT + 'radar.png', imageShape: 'circular'
	},
	// Level 1
	{ price: 75, resaleValue: 100, radius: 150, angularVelocity: Math.PI / 2,
		image: IMAGE_ROOT + 'radar.png', imageShape: 'circular'
	}
];

/**
 * This class field saves the price needed to buy a new Radar
 */
Radar.BUY_PRICE = Radar.UPGRADE_LIST[0].price;

/**
 * Return the length of the detector ray.
 *
 * @return {number} The length of the ray, in pixel.
 */
Radar.prototype.getRadius = function() {
	return this.getLevelSettings().radius;
};

/**
 * Return the angular velocity of the detector ray.
 *
 * @return {number} The angular velocity, in rad/s.
 */
Radar.prototype.getAngularVelocity = function() {
	return this.getLevelSettings().angularVelocity;
};


/**
 * Sets the angle where the detection starts.
 *
 * @param {number} angle The angle where the detection starts
 * @throws {TypeError} Throws this exception if angle's type isn't 'number'.
 */
Radar.prototype.setStartAngle = function(angle) {
	if (typeof angle !== 'number') {
		throw new TypeError();
	}
	else {
		this.startAngle = angle % (Math.PI * 2);
		this.currentAngle = this.startAngle;
	}
};

/**
 * Return the radar startAngle
 *
 * @return {Number} The radar startAngle
 */
Radar.prototype.getStartAngle= function() {
	return this.startAngle;
};

/**
 * Sets the angle covered by the radar.
 *
 * @param {number} angle The angle covered by the radar.
 * @throws {TypeError} Throws this exception if angle's type isn't 'number'.
 * @throws {RangeError} Throws this exception if angle's value isn't valid.
 */
Radar.prototype.setCentralAngle = function(angle) {
	if (typeof angle !== 'number') {
		throw new TypeError();
	}
	else if (angle > Math.PI * 2){
		throw new RangeError();
	}
	else {
		this.centralAngle = angle;
	}
};

/**
 * Return the radar centralAngle
 *
 * @return {Number} The radar centralAngle
 */
Radar.prototype.getCentralAngle= function() {
	return this.centralAngle;
};

/**
 * Updates the position of the detector ray of the radar.
 *
 * @param {number} msDuration The time past from the last call, in ms.
 */
Radar.prototype.update = function(msDuration) {
	// Calculate the angle covered by the ray and update the currentAngle
	var coveredAngle = this.getAngularVelocity() * msDuration / 1000;
	this.currentAngle = (this.currentAngle + coveredAngle) % this.centralAngle;
	var totalAngle = this.startAngle + this.currentAngle;

	// Variables used inside for loop
	var rayEndX, rayEndY, rayEnd, rayLenght, enemies, i;
	var currentMap = this.getMatchMap();

	// Check collisions
	for(rayLenght = this._minRayLength; rayLenght <= this.getRadius();
		rayLenght++) {
		rayEndX = Math.ceil(
			this.getCenter()[0] + Math.cos(totalAngle) * rayLenght
		);
		rayEndY = Math.ceil(
			this.getCenter()[1] + Math.sin(totalAngle) * rayLenght
		);
		rayEnd = [rayEndX, rayEndY];

		// Detect all the enemies on the current ray position
		enemies = currentMap.getEnemies().sprites();
		for (i = 0; i < enemies.length; i++) {
			if (enemies[i].rect.collidePoint(rayEnd)) {
				enemies[i].setDetected(true);
			}
		}

		// If the ray end position is outside the map or filled by something
		// else we must stop here
		if(! currentMap.isInRange(rayEnd) || currentMap.isFilled(rayEnd)){
			break;
		}
	}

	// Update internal variables
	this._currentRayEnd = rayEnd;
};

/**
 * Draws the radar in the given Surface.
 *
 * @param {gamejs.Surface} surface The Surface where draw on.
 */
Radar.prototype.draw = function(surface) {
	// Draw the ray
	gamejs.draw.line(surface, '#33FF00',
		this.getCenter(), this._currentRayEnd, 2
	);
	// Draw the radar
	surface.blit(this.image, this.rect.topleft);
};